package com.llh.controller.http.common;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.llh.bean.TradeLog;
import com.llh.controller.http.TradeCal;
import com.llh.mapper.TradeLogMapper;
import com.llh.pojo.common.*;
import com.llh.pojo.trade.requestBean.common.RequestParams;
import com.llh.pojo.trade.responseBean.common.RespParams;
import com.llh.pojo.trade.result.common.HttpData;
import com.llh.pojo.trade.result.common.HttpResult;
import com.llh.util.MyStringUtil;
import com.llh.util.SqlSessionUtil;
import lombok.Data;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.util.EntityUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import java.io.IOException;
import java.util.Date;

@Data
public abstract class CommonExcuteTrade implements CommonTrade {
    static Logger logger = LogManager.getLogger(TradeCal.class.getName());
    //api接口名
    private String apiName;
    //请求体参数
    private RequestParams params;
    //响应数据param实体类,想要的字段设置为true
    private RespParams respParams;
    //请求体json格式字符串
    private TradeLog tradeLog;

    /**
     * 交易接口
     *
     * @return
     * @throws Exception
     */
    @Override
    public String doService(int flag) throws Exception {
        Date now = new Date();
        //正常发请求
        if (flag == 0) {
            CommonReqTool commonReqTool = new CommonReqTool();
            CommonReqEntity reqEntity = new CommonReqEntity();
            //交易码
            reqEntity.setApi_name(apiName);
            //想要的数据字段名
            CommonFiledTool commonFiledTool = new CommonFiledTool();
            commonFiledTool.setRespFields(respParams);
            boolean b = commonFiledTool.init();
            if (!b) {
                throw new Exception("设置返回fields失败");
            }
            reqEntity.setFields(commonFiledTool.getFields());
            //请求条件参数
            reqEntity.setParams(params);
            String reqJson = JSON.toJSONString(reqEntity);
            logger.info("请求体:" + reqJson);
            CloseableHttpResponse response = null;
            boolean init = commonReqTool.init(reqEntity);
            if (init) {
                try {
                    response = commonReqTool.sendPost();
                    int statusCode = response.getStatusLine().getStatusCode();
                    if (statusCode != 200) {
                        logger.error("调用接口http响应失败");
                        //将发送失败的请求存入数据库
                        TradeLog tradeLog = new TradeLog();
                        tradeLog.setTrade_code(apiName);
                        tradeLog.setReq_json(reqJson);
                        //是否从新尝试过了的标志初始化为0
                        tradeLog.setRetry(0);
                        //插入时间为当前时间
                        tradeLog.setInsert_time(now);
                        //错误原因
                        tradeLog.setReason("http:"+statusCode);
                        HttpEntity entity = response.getEntity();
                        String respJson = null;
                        if (entity != null) {
                            respJson = EntityUtils.toString(entity, "UTF-8");
                        }
                        //响应体json字符串
                        tradeLog.setResp_json(MyStringUtil.subStrByStrAndLen(respJson,250));
                        SqlSession sqlSesion = null;
                        try {
                            sqlSesion = SqlSessionUtil.getSqlSesion();
                            TradeLogMapper mapper = sqlSesion.getMapper(TradeLogMapper.class);
                            logger.error("插入请求失败日志:" + tradeLog.toString());
                            mapper.insertSelective(tradeLog);
                        } catch (Exception e){
                            e.printStackTrace();
                            throw new Exception("http请求失败,响应码:"+statusCode+"且记录错误日志数据库操作也报错");
                        }
                        finally {
                            sqlSesion.close();
                        }
                        throw new Exception("http请求失败,响应码:"+statusCode+",错误日志已经记录到数据库");

                    }

                    String convert = CommonRespTool.convert(response);
                    logger.info("响应体:"+convert);
                    //请求成功,就验证请求体的响应码是否为0
                    HttpResult httpResult = JSON.parseObject(convert, new TypeReference<HttpResult>() {
                    });
//                    String code = httpResult.getCode();
                    String msg = httpResult.getMsg();
                    if (!(msg==null||"".equals(msg))) {

                        //不等于0则为平台响应没成功
                        logger.error("调用接口http响应失败");
                        //将发送失败的请求存入数据库
                        TradeLog tradeLog = new TradeLog();
                        tradeLog.setTrade_code(apiName);
                        tradeLog.setReq_json(reqJson);
                        //是否从新尝试过了的标志初始化为0
                        tradeLog.setRetry(0);
                        //插入时间为当前时间
                        tradeLog.setInsert_time(now);
                        //错误原因
                        tradeLog.setReason("api:"+msg);
                        //响应体json字符串
                        tradeLog.setResp_json(MyStringUtil.subStrByStrAndLen(convert,200));
                        SqlSession sqlSesion = null;
                        try {
                            sqlSesion = SqlSessionUtil.getSqlSesion();
                            TradeLogMapper mapper = sqlSesion.getMapper(TradeLogMapper.class);
                            logger.error("插入请求失败日志:" + tradeLog.toString());
                            mapper.insertSelective(tradeLog);
                        } catch (Exception e){
                            e.printStackTrace();
                            throw new Exception("api平台响应错误:"+msg+"且修改记录错误日志数据库操作也报错");
                        }
                        finally {
                            sqlSesion.close();
                        }
                        throw new Exception("api平台响应错误:"+msg+",错误日志修改成功");

                    }

                    return convert;
                } finally {
                    try {
                        if (commonReqTool != null) {
                            commonReqTool.httpClient.close();
                        }
                        if (commonReqTool != null) {
                            response.close();
                        }

                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                }
            } else {
                throw new Exception("调用接口时请求参数对象解析错误");
            }

            //错误接口重新调取的flag = 1;
        } else if (flag == 1) {
            CommonReqTool commonReqTool = new CommonReqTool();
            if (tradeLog == null) {
                throw new Exception("trade 对象为空");
            }
            String req_json = tradeLog.getReq_json();
            boolean init = commonReqTool.init(req_json);
            CloseableHttpResponse response = null;
            if (init) {
                try {
                    response = commonReqTool.sendPost();
                    int statusCode = response.getStatusLine().getStatusCode();
                    if (statusCode != 200) {
                        logger.error("http请求失败");
                        HttpEntity entity = response.getEntity();
                        String respJson = null;
                        if (entity != null) {
                            respJson = EntityUtils.toString(entity, "UTF-8");
                        }
                        tradeLog.setResp_json(MyStringUtil.subStrByStrAndLen(respJson,250));
                        //执行过了执行
                        tradeLog.setRetry(1);
                        //执行失败
                        tradeLog.setRetry_result("失败");
                        //失败原因
                        tradeLog.setReason("http:"+statusCode);
                        //重新执行时间
                        tradeLog.setTime(now);
                        SqlSession sqlSesion = null;
                        try {
                            sqlSesion = SqlSessionUtil.getSqlSesion();
                            TradeLogMapper mapper = sqlSesion.getMapper(TradeLogMapper.class);
                            logger.error("插入请求失败日志:" + tradeLog.toString());
                            mapper.updateByPrimaryKeySelective(tradeLog);
                        } catch (Exception e){
                            e.printStackTrace();
                            throw new Exception("http请求失败,响应码:"+statusCode+"且修改错误日志数据库操作也报错");
                        }
                        finally {
                            sqlSesion.close();
                        }
                        throw new Exception("http请求失败,响应码:"+statusCode);

                    }
                    String convert = CommonRespTool.convert(response);
                    //请求成功,就验证请求体的响应码是否为0
                    HttpResult httpResult = JSON.parseObject(convert, new TypeReference<HttpResult>() {
                    });
                    String msg = httpResult.getMsg();
                    if (!(msg==null||"".equals(msg))) {
                        //不等于0则为平台响应没成功
                        logger.error("调用api平台响应失败");
                        tradeLog.setResp_json(MyStringUtil.subStrByStrAndLen(convert,250));
                        //执行过了执行
                        tradeLog.setRetry(1);
                        //执行失败
                        tradeLog.setRetry_result("失败");
                        //失败原因
                        tradeLog.setReason("api:"+statusCode);
                        //重新执行时间
                        tradeLog.setTime(now);
                        SqlSession sqlSesion = null;
                        try {
                            sqlSesion = SqlSessionUtil.getSqlSesion();
                            TradeLogMapper mapper = sqlSesion.getMapper(TradeLogMapper.class);
                            logger.error("插入请求失败日志:" + tradeLog.toString());
                            mapper.insertSelective(tradeLog);
                        }catch (Exception e){
                            e.printStackTrace();
                            throw new Exception("api请求失败::"+msg+"且修改错误日志数据库操作也报错");
                        }
                        finally {
                            sqlSesion.close();
                        }
                        throw new Exception("api平台响应错误");

                    }else{
                        tradeLog.setResp_json(MyStringUtil.subStrByStrAndLen(convert,250));
                        //执行过了执行
                        tradeLog.setRetry(1);
                        //执行失败
                        tradeLog.setRetry_result("成功");
                        //重新执行时间
                        tradeLog.setTime(now);
                        SqlSession sqlSesion = null;
                        try {
                            sqlSesion = SqlSessionUtil.getSqlSesion();
                            TradeLogMapper mapper = sqlSesion.getMapper(TradeLogMapper.class);
                            logger.error("插入请求失败日志:" + tradeLog.toString());
                            mapper.insertSelective(tradeLog);
                        } catch (Exception e){
                            e.printStackTrace();
                            throw new Exception("api请求成功:"+msg+",但是修改错误日志数据库操作报错");
                        }
                        finally {
                            sqlSesion.close();
                        }
                    }

                    return convert;
                } finally {
                    try {
                        if (commonReqTool != null) {
                            commonReqTool.httpClient.close();
                        }
                        if (commonReqTool != null) {
                            response.close();
                        }

                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                }
            } else {
                throw new Exception("调用接口时请求参数对象解析错误");
            }
        }else{
            logger.error("doservice()传参错误");
            throw new Exception("doservice()传参错误");
        }


    }

    /**
     * 处理响应对象
     *
     * @param result
     * @throws Exception
     */
    @Override
    public void parseResult(String result) throws Exception {
        HttpResult httpResult = JSON.parseObject(result, new TypeReference<HttpResult>() {
        });
        String code = httpResult.getCode();
        if (code.equals("0")) {
            //请求成功
            HttpData data = httpResult.getData();
            //[exchange,cal_date,is_open,pretrade_date]
            String[] fields = data.getFields();
            String[][] items = data.getItems();
            //调用处理param参数的方法(param就是最终需要的数据)
            parseParam(items, fields);


        }
    }

}
